/*
   RxInputManager
   Copyright 2011 Jordan Neumeyer

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
   
   File: RxInputManager.cs 
 */

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework;
using RxInputManager.Interfaces;
using RxInputManager.Devices;
using System;

namespace RxInputManager
{
    public class RxInputService : 
        IRxInputService, IGameComponent,
        IUpdateable, IDisposable 
    {
        private List<IRxKeyboard> keyboards;
        public ReadOnlyCollection<IRxKeyboard> Keyboards
        {
            get { return keyboards.AsReadOnly(); }
        }

        private List<IRxMouse> mice;
        public ReadOnlyCollection<IRxMouse> Mice
        {
            get { return mice.AsReadOnly(); }
        }

        private List<IRxGamePad> gamepads;
        public ReadOnlyCollection<IRxGamePad> Gamepads
        {
            get { return gamepads.AsReadOnly(); }
        }

        public IRxKeyboard GetKeyboard()
        {
            return keyboards[0];
        }

        public IRxMouse GetMouse()
        {
            return mice[0];
        }

        public IRxGamePad GetGamePad(PlayerIndex playerID)
        {
            return gamepads[(int)playerID];
        }

        public void Update()
        {
            gamepads.ForEach(gamepad => gamepad.Update());
            mice.ForEach(mouse => mouse.Update());
            keyboards.ForEach(keyboard => keyboard.Update());
        }

        private GameServiceContainer gameservice;

        public RxInputService() : this(null)
        {

        }

        public RxInputService(GameServiceContainer container)
        {
            if (null != container)
            {
                // Change scheduler here if they provided a game container.
                gameservice = container;
                gameservice.AddService(typeof(IRxInputService), this);
            }

            SetupControllers();
            SetupKeyboard();
            SetupMice();
        }


        public void SetupControllers()
        {
#if WINDOWS || XBOX
            gamepads = new List<IRxGamePad>(4);

            for (var player = PlayerIndex.One; player <= PlayerIndex.Four; ++player)
                gamepads.Add(new RxGamePad(player));
#endif
        }

        public void SetupMice()
        {
#if WINDOWS
            mice = new List<IRxMouse>(1) { new RxMouse() };
#else
            mice = new List<IRxMouse>(1) { new NoMouse() };
#endif
        }

        public void SetupKeyboard()
        {
#if WINDOWS
            keyboards = new List<IRxKeyboard>(1) { new RxKeyboard() };
#else
            keyboards = new List<IRxKeyboard>(1) { new NoKeyboard() };
#endif
        }

        void IGameComponent.Initialize()
        {
            // Don't think I need to do anything here. 
        }

        public void Dispose()
        {
            gamepads.ForEach(gamepad => gamepad.Dispose() );
            mice.ForEach(mouse => mouse.Dispose());
            keyboards.ForEach(keyboard => keyboard.Dispose());
        }

        public bool Enabled
        {
            get { return true; }
        }

        public event EventHandler<EventArgs> EnabledChanged;

        public void Update(GameTime gameTime)
        {
            this.Update();
        }

        private int UpdateOrderValue = int.MinValue;
        public int UpdateOrder
        {
            get { return UpdateOrderValue; }
            set
            {
                UpdateOrderValue = value;
                if (null != UpdateOrderChanged)
                    UpdateOrderChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler<EventArgs> UpdateOrderChanged;
    }
}
